package com.google.code.mochaccino.framework.ui.demo;
/*
 * Copyright 2012 Claude Houle claude.houle@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.google.code.mochaccino.framework.rest.Root;
import com.google.code.mochaccino.framework.security.SecurityRealmPOJO;
import com.google.code.mochaccino.framework.ui.components.TreeLeaf;
import com.google.code.mochaccino.framework.ui.components.TreeNode;
import com.google.code.mochaccino.framework.ui.demo.pages.Frame;
import com.google.code.mochaccino.framework.ui.demo.pages.FrameService;
import com.google.code.mochaccino.framework.ui.demo.pages.LoginService;
import com.google.code.mochaccino.framework.ui.demo.pages.UserSettings;
import com.google.code.mochaccino.framework.ui.demo.pages.UserSettingsService;
import com.google.code.mochaccino.framework.ui.demo.pages.UserSettingsService.UserInfo;
import com.google.code.mochaccino.framework.ui.services.ServiceResult;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.inject.Singleton;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.mockito.Matchers;
import org.mockito.Mockito;

/**
 *
 */
public class ApplicationServiceModule extends AbstractModule {
	public static final UserInfo createInvalidUser() {
		return new UserInfo( 2, -1, "Root1", "Steve", "Jobs", "steve@apple.com", Locale.ENGLISH.toString(), 15 );
	}

	public static final UserInfo createValidUser() {
		return new UserInfo( 1, -1, "Root", "Steve", "Jobs", "steve@apple.com", Locale.ENGLISH.toString(), 15 );
	}

	@Override
	protected void configure() {
		bind( FilterChainResolver.class ).to( PathMatchingFilterChainResolver.class );
	}

	@Provides
	FrameService provideFrameService() {
		FrameService service = Mockito.mock( FrameService.class );
		Mockito.when( service.getEnvironment() ).thenReturn( "choule" );
		Mockito.when( service.getFullName( Matchers.anyString() ) ).thenReturn( "Mr. John Doe" );
		Mockito.when( service.getHelpUrl() ).thenReturn( "http://www.google.ca/" );
		Mockito.when( service.getSettingsUrl( Matchers.anyString() ) ).thenReturn( "http://apple.ca/iphone" );

		List<TreeNode> modules = new ArrayList<TreeNode>();
		modules.add( new TreeNode( "Module 1", false, new TreeLeaf( "View 1", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 2", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 3", Root.PATH_LOGOUT, false ) ) );
		modules.add( new TreeNode( "Module 2", false, new TreeLeaf( "View 1", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 2", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 3", Root.PATH_LOGOUT, false ) ) );
		modules.add( new TreeNode( "Module 3", false, new TreeLeaf( "View 1", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 2", Root.PATH_LOGOUT, false ), new TreeLeaf( "View 3", Root.PATH_LOGOUT, false ) ) );
		Mockito.when( service.getTreeNodes( Matchers.anyString() ) ).thenReturn( modules );

		return service;
	}

	@Provides
	LoginService provideLoginService() {
		LoginService service = Mockito.mock( LoginService.class );

		/**
		 * Generic Login Rendering
		 */
		Mockito.when( service.getEnvironment() ).thenReturn( "choule" );
		Mockito.when( service.getLanguages() ).thenReturn( Arrays.asList( Locale.ENGLISH, Locale.FRENCH ) );

		/**
		 * Support the successful login
		 */
		try {
			Mockito.when( service.getSuccessLoginURL() ).thenReturn( new URI( Frame.PATH ) );
		} catch ( URISyntaxException e ) {
			throw new RuntimeException( e );
		}

		/**
		 * Support the Change password required
		 */
		Mockito.when( service.passwordChangeRequired( "Root1" ) ).thenReturn( true );

		/**
		 * SUPPORT the change password flow
		 */
		Mockito.when( service.getChangePasswordToken( "Root1" ) ).thenReturn( "123" );
		Mockito.when( service.validateToken( "Root1", "123" ) ).thenReturn( true );
		Mockito.when( service.changePassword( Matchers.eq( "Root1" ), Matchers.eq( "123" ), Matchers.anyString(), Matchers.anyString() ) ).thenReturn( true );

		return service;
	}

	@Singleton
	@Provides
	Realm[] provideRealms() {
		SecurityRealmPOJO bean = new SecurityRealmPOJO();

		SimpleAccount root = new SimpleAccount( "Root", "123", bean.getName(), null, null );
		root.addStringPermission( Frame.PRIV_FRAME );
		root.addStringPermission( UserSettings.PRIV_EDIT_INFO );
		root.addStringPermission( UserSettings.PRIV_EDIT_MODULES );
		root.addStringPermission( UserSettings.PRIV_EDIT_PASSWORD );
		bean.add( root );

		SimpleAccount root1 = new SimpleAccount( "Root1", "123", bean.getName(), null, null );
		root1.addStringPermission( Frame.PRIV_FRAME );
		root1.addStringPermission( UserSettings.PRIV_EDIT_INFO );
		root1.addStringPermission( UserSettings.PRIV_EDIT_MODULES );
		root1.addStringPermission( UserSettings.PRIV_EDIT_PASSWORD );
		bean.add( root1 );

		return new Realm[] { bean };
	}

	@Provides
	UserSettingsService provideUserSettings() {
		UserSettingsService service = Mockito.mock( UserSettingsService.class );
		Mockito.when( service.getAvailableLocale() ).thenReturn( Arrays.asList( Locale.ENGLISH, Locale.FRENCH ) );
		Mockito.when( service.getUserInfo( "Root" ) ).thenReturn( createValidUser() );
		Mockito.when( service.getUserInfo( "Root1" ) ).thenReturn( createInvalidUser() );
		Mockito.when( service.getMinimumConsoleTimeout() ).thenReturn( 15 );
		Mockito.when( service.getMaximumConsoleTimeout() ).thenReturn( 60 );
		Mockito.when( service.saveUserInfo( Matchers.eq( createValidUser() ), (Locale) Matchers.anyObject() ) ).thenReturn( ServiceResult.success() );
		Mockito.when( service.saveUserInfo( Matchers.eq( createInvalidUser() ), (Locale) Matchers.anyObject() ) ).thenReturn( ServiceResult.fail( "Username 'Root1' already exist!" ) );
		return service;
	}
}
